昨天談「完成」的依據。今天談「每個部分都完成了」之後的事。
三個模組,各自的測試都過。組起來,報告說平均長度 152.5 公尺。實際是 152.5 公分。
我目前把它寫成這樣:
子任務各自正確,只有在它們的介面與共同限制也相容時,才能支持整體成果正確。
前提是:整體成果是由子任務組合出來的。各自正確是必要條件,不是充分條件。少的那一塊叫介面:A 交出去的東西,B 拿到手時,兩邊對它的理解一不一樣。
它也不是在說一定要拆成很多步。未來的模型可以自動管理所有相依關係,甚至一次做完更有效。本律不保證多拆幾步更好,它只檢查局部通過與整體通過之間有沒有落差。
還有一條老規矩:沒跑過的實驗不能寫得像有結果;小樣本不能說成普遍現象。
一個從資料到報告的小流程,三個模組:
read_lengths() 回傳三根樣本的長度,docstring 寫「單位:公分」。average(xs) 回算術平均。report(mean_m) 把平均格式化成「平均長度 X 公尺」,docstring 寫「mean_m:單位公尺」。
各自都對。各自的單元測試都過。組起來:report(average(read_lengths())),輸出「平均長度 152.50 公尺」。錯了一百倍。
三種檢查方式,程式碼相同,差在陪同的東西:
| 條件 | 陪同的證據 |
|---|---|
| W 一次看整條 | 組合流程和輸出 |
| S 只驗子成果 | 四條單元測試,全部 PASSED |
| I 驗介面 | 一張介面表,列每個模組的輸入輸出單位 |
問題固定:最終報告對不對。輸出一行,「正確」或「有錯:一句說明」。
模型是 Claude Haiku 4.5,每條件四次,共十二次。
有沒有說有錯,理由有沒有提到單位。程式判。
S 是檢驗點。陪同的證據是「各模組測試皆通過」。如果 S 說「正確」的次數比 W 和 I 多,就示範了局部通過誤導整體判斷。
也事先寫了:三條件都 4 次全抓到,本律成立但落差未被示範,如實報告。單位錯接在 docstring 裡明寫,屬於容易案例。
材料、判準、預期,在第一次呼叫之前提交進版本控制。
| 條件 | 抓到單位錯接 | 說正確 |
|---|---|---|
| W 一次看整條 | 4/4 | 0 |
| S 只驗子成果 | 4/4 | 0 |
| I 驗介面 | 4/4 | 0 |
十二次全部指出公分接到公尺,多數還算出正確值 1.53 公尺。
落在事先寫的「未被示範」。
S 組是我最想看的。四條 PASSED 擺在眼前,每個模組都被證明是對的。模型四次都沒有因此說整體正確。
它看的不是測試。它看的是 docstring:一個說公分,一個說公尺,中間沒有換算。這個資訊在程式碼裡,不在測試裡。測試只證明每個模組自己對,沒有一條測試碰到模組之間的那條線。
所以今晚的結果是:當介面的規格寫在看得到的地方,「各自通過」沒有騙到人。
得說清楚為什麼今晚太容易。
真實的整合錯誤,單位通常不在 docstring 裡。read_lengths 就叫 read_lengths,寫它的人心裡知道是公分,沒寫。report 的作者心裡想的是公尺,也沒寫。兩個人各自的測試都過,因為各自的測試用的是各自心裡的單位。錯接發生在兩個腦袋之間,程式碼上沒有痕跡。
那種情況下,S 組會不會還是 4/4,我不知道。本次沒測。本律描述的落差,要在那種情況下才會出現。
第一,一個流程、一種錯誤、每條件四次。
第二,單位明寫。 隱含單位未測。
第三,沒比較分解和一次完成的產出。 只比較檢查方式。
這條律是關於充分條件的陳述。一個反例就夠:找到一組子任務,各自正確、介面不相容、整體卻對。今晚的介面不相容,整體就錯了,沒有反例。
另一條路:如果 S 出現「正確」,示範了局部通過誤導整體。今晚零次。
替每條線寫一行。
不是替每個模組,是替每條連接。A 交給 B 的是什麼,單位是什麼,範圍是什麼。今晚 I 組那張介面表就是這個東西。它沒有讓 I 組比 S 組好,因為 docstring 已經把單位寫了。但 docstring 沒寫的那天,那張表是唯一會有的地方。
紀錄表這次加的是一欄:「每條線的單位」。
本文的協作紀錄是:三個模組、三份提示詞、判定程式與預期在任何一次呼叫之前提交,之後未修改;十二次輸出逐字保留,判定由程式執行;一次輸出帶有 subagent 洩漏的署名行,逐字保留。文章由 Claude 根據作者整理的寫作規則起草,作者尚未核對。這篇沒有做 Day 2 那種六個審查者的檢查。
下一篇談 AI 說「完成了」,外面的世界真的改變了嗎。